package mx.gob.imss.reiman.clientes.service.impl;

import hl7OrgV3.PRPAMT201310Patient;
import hl7OrgV3.PRPAMT201310Person;
import hl7OrgV3.QUQIMT000002Component;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

import mx.gob.imss.reiman.clientes.model.Persona;
import mx.gob.imss.reiman.clientes.model.mensajes.Mensaje;
import mx.gob.imss.reiman.clientes.model.mensajes.MensajeIMP;
import mx.gob.imss.reiman.clientes.service.MensajeriaService;
import mx.gob.imss.reiman.clientes.service.SOAPService;
import noNamespace.GovTalkMessageDocument.GovTalkMessage.GovTalkDetails.GovTalkErrors.Error;

import org.apache.xmlbeans.XmlException;
import org.openuri.ConsultarPAIMPDocument;
import org.openuri.ConsultarPAIMPResponseDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 
 * @author Alberto Dzul Calvillo
 * @version 1.0
 * 
 */
@Service("consultaIMPService")
public class ConsultaIMPServiceImpl implements MensajeriaService {
	private static final String nodo = "consultarPAIMPResponse";
	@Autowired
	private SOAPService soapService;

	@Override
	public void enviar(Mensaje mensaje, String endpoint)
			throws MalformedURLException, UnsupportedOperationException,
			XmlException, SOAPException {
		enviar(mensaje, endpoint, false);
	}

	public void enviar(Mensaje mensaje, String endpoint, boolean xml)
			throws MalformedURLException, UnsupportedOperationException,
			XmlException, SOAPException {
		MensajeIMP mensajeIMP = (MensajeIMP) mensaje;
		ConsultarPAIMPDocument document = ConsultarPAIMPDocument.Factory
				.parse(xml ? mensaje.getXml().toString()
						:getXMLConsulta(mensajeIMP.getPersona()));
		SOAPMessage response = soapService.enviar(document.getDomNode(),
				endpoint);
		if (response != null) {
			mensajeIMP
					.setPersonas(obtenResultadosConsulta(response, mensajeIMP));
		} else {
		}
	}

	private List<Persona> obtenResultadosConsulta(SOAPMessage response,
			MensajeIMP mensaje) throws XmlException, SOAPException {
		SOAPBody body = response.getSOAPPart().getEnvelope().getBody();
		NodeList nodeList = body.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); ++i) {
			Node node = nodeList.item(i);
			String localName = node.getLocalName();
			if (nodo.equals(localName)) {
				return obtenerDatosDelNodoConsultar(node, mensaje);
			}
		}
		return new ArrayList<Persona>();
	}

	private List<Persona> obtenerDatosDelNodoConsultar(Node node,
			MensajeIMP mensaje) throws XmlException {
		ConsultarPAIMPResponseDocument document = ConsultarPAIMPResponseDocument.Factory
				.parse(node);
		@SuppressWarnings("deprecation")
		Error[] errores = document.getConsultarPAIMPResponse()
				.getGovTalkMessage().getGovTalkDetails().getGovTalkErrors()
				.getErrorArray();
		List<Persona> personas = new ArrayList<Persona>();
		try {
			personas = cargaDatos(document);
		} catch (Exception e) {
			logger.error(e.getMessage());
		} catch (NoSuchMethodError e) {
			logger.error(e.getMessage());
		}
		for (Error error : errores) {
			mensaje.getErrores().add(
					new mx.gob.imss.reiman.clientes.model.Error(error
							.getNumber().toString(), error.getTextArray(0)));
		}
		return personas;
	}

	private List<Persona> cargaDatos(ConsultarPAIMPResponseDocument document) {
		PRPAMT201310Patient patient = null;
		PRPAMT201310Person person = null;
		List<QUQIMT000002Component> listComp = new ArrayList<QUQIMT000002Component>();
		Persona pa = new Persona();
		List<Persona> pas = new ArrayList<Persona>();
		try {
			listComp = document.getConsultarPAIMPResponse().getGovTalkMessage()
					.getGenericQueryResponseArray(0)
					.getGenericQueryControlAct().getComponentList();
		} catch (NullPointerException npe) {
		}
		for (QUQIMT000002Component comp : listComp) {
			pa = new Persona();
			patient = null;
			person = null;
			patient = comp.getPatient();
			person = patient.getPatientPerson();
			try {
				pa.setNss(person.getId().getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setCurp(person.getAsCitizen().getId().getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setApellidoPaterno(getContent(person.getName()
						.getFamilyArray(0).toString()));
			} catch (Exception e) {
			}
			try {
				pa.setApellidoMaterno(getContent(person.getName()
						.getGivenArray(0).toString()));
			} catch (Exception e) {
			}
			try {
				pa.setNombre(getUse(person.getName().xmlText()));
			} catch (Exception e) {
			}
			try {
				pa.setSexo(person.getAdministrativeGenderCode().getCode());
			} catch (Exception e) {
			}
			try {
				pa.setFechaNacimiento(person.getBirthTime().getValue());
			} catch (Exception e) {
			}
			try {
				pa.setRfc(person.getAsEmployment().getId().getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setUnidad(getContent(person.getGuardian().getOrganization()
						.getDesc().toString()));
			} catch (Exception e) {
			}
			try {
				pa.setAgregadoMedico(person.getAsOtherIDs().getId()
						.getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setTelefono(person.getTelecom().getValue());
			} catch (Exception e) {
			}
			try {
				pa.setIdMunicipio(getContent(person.getAddr().getCityArray(0)
						.toString()));
			} catch (Exception e) {
			}
			try {
				pa.setCp(getContent(person.getAddr().getPostalCodeArray(0)
						.toString()));
			} catch (Exception e) {
			}
			try {
				pa.setCalle(getContent(person.getAddr().getStreetNameArray(0)
						.toString()));
			} catch (Exception e) {
			}
			try {
				pa.setNumeroExterior(getContent(person.getAddr()
						.getHouseNumberArray(0).toString()));
			} catch (Exception e) {
			}
			try {
				pa.setNumeroInterior(getContent(person.getAddr()
						.getHouseNumberNumericArray(0).toString()));
			} catch (Exception e) {
			}
			try {
				pa.setColonia(getContent(person.getAddr()
						.getAdditionalLocatorArray(0).toString()));
			} catch (Exception e) {
			}
			try {
				pa.setTipoPaciente(patient.getId().getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setFechaDefuncion(person.getDeceasedTime().getValue());
			} catch (Exception e) {
			}
			try {
				pa.setFechaLabores(person.getAsEmployment().getEffectiveTime()
						.getValue());
			} catch (Exception e) {
			}
			try {
				pa.setFechaVigencia(person.getGuardian().getEffectiveTime()
						.getValue());
			} catch (Exception e) {
			}
			try {
				pa.setRegistroPatronal(person.getGuardian().getOrganization()
						.getId().getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setCvePREI(person.getGuardian().getOrganization().getCode()
						.getCode());
			} catch (Exception e) {
			}
			try {
				pa.setRazonSocial(getUse(person.getGuardian().getOrganization()
						.getName().xmlText()));
			} catch (Exception e) {
			}
			try {
				pa.setConsultorio(person.getGuardian().getOrganization()
						.getContactPartyArray(0).getId().getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setTurno(person.getGuardian().getOrganization()
						.getContactPartyArray(0).getStatusCode().getCode());
			} catch (Exception e) {
			}
			try {
				pa.setSituacion(person.getGuardian().getOrganization()
						.getContactPartyArray(0).getContactPerson()
						.getStatusCode().getCode());
			} catch (Exception e) {
			}
			try {
				pa.setDerechoIncapacidad(person.getGuardian().getOrganization()
						.getContactPartyArray(0).getContactPerson()
						.getDisabilityCode().getCode());
			} catch (Exception e) {
			}
			try {
				pa.setTipoPension(person.getGuardian().getCoveredPartyOf()
						.getPensions().getIdArray(0).getExtension());
			} catch (Exception e) {
			}
			try {
				pa.setDescripcionTipoPension(getContent(person.getGuardian()
						.getCoveredPartyOf().getPensions().getText().toString()));
			} catch (Exception e) {
			}
			try {
				pa.setAgregadoAfiliacion(person.getAsOtherIDs().getCode()
						.getCode());
			} catch (Exception e) {
			}
			try {
				pa.setIdee(person.getGuardian().getId().getExtension());
			} catch (Exception e) {
			}
			pas.add(pa);
		}
		return pas;
	}

	private String getUse(String name) {
		int i1 = -1;
		int i2 = -1;
		int i3 = -1;
		String tmp = "";
		i1 = name.indexOf("use");
		if (i1 < 0)
			return "";
		i1 += 3;
		tmp = name.substring(i1);
		i2 = tmp.indexOf("\"");
		name = tmp.substring(i2 + 1);
		i3 = name.indexOf("\"");
		tmp = name.substring(0, i3);
		return tmp;
	}

	private String getContent(String xmlFragment) {
		int i1 = -1;
		int i2 = -1;
		int i3 = -1;
		i1 = xmlFragment.indexOf(">");
		i2 = xmlFragment.indexOf("</");
		i3 = xmlFragment.indexOf("/>");
		if (i3 > 0)
			return "";
		if (i1 < 0 || i2 < 0)
			return "";
		return xmlFragment.substring(i1 + 1, i2);
	}

	private String getXMLConsulta(Persona pa) {
		StringBuilder sb = new StringBuilder();
		sb.append("<consultarPAIMP xmlns='http://www.openuri.org/'>\n");
		sb.append("  <GovTalkMessage xmlns='urn:hl7-org:v3'>\n");
		sb.append("  <EnvelopeVersion>2.0</EnvelopeVersion>\n");
		sb.append("	   <Header>\n");
		sb.append("	     <MessageDetails>\n");
		sb.append("	   		<Class>PRPA_RM201301</Class>\n");
		sb.append("	   		<Qualifier>HL7Message</Qualifier>\n");
		sb.append("	   		<Function>submit</Function>\n");
		sb.append("	   		<TransactionID/>\n");
		sb.append("	   		<CorrelationID/>\n");
		sb.append("	   		<GatewayTimestamp>01:01:01 2011/01/01</GatewayTimestamp>\n");
		sb.append("      </MessageDetails>\n");
		sb.append("	   	<SenderDetails>\n");
		sb.append("	   		<SenderIP>11.254.16.122</SenderIP>\n");
		sb.append("	   		<Authentication>\n");
		sb.append("	   			<Method>clear</Method>\n");
		sb.append("	   			<Value/>\n");
		sb.append("	   		</Authentication>\n");
		sb.append("	   	</SenderDetails>\n");
		sb.append("	   	<ReceiverDetails>\n");
		sb.append("	   		<SenderIP>11.254.16.122</SenderIP>\n");
		sb.append("	   		<Authentication>\n");
		sb.append("	   			<Method>clear</Method>\n");
		sb.append("	   			<Value/>\n");
		sb.append("	   		</Authentication>\n");
		sb.append("	   	</ReceiverDetails>\n");
		sb.append("	   </Header>\n");
		sb.append("    <GovTalkDetails>\n");
		sb.append("    	<TargetDetails>\n");
		sb.append("    		<Organization>IMSS</Organization>\n");
		sb.append("    	</TargetDetails>\n");
		sb.append("    </GovTalkDetails>\n");
		sb.append("    <Body>\n");
		sb.append("    <QueryByParameter xmlns='urn:hl7-org:v3' xmlns:xsi='http://www.w3.org/2002/XMLSchema-instance' xsi:schemaLocation='urn:hl7-org:v3 PRPA_HD201307.xsd'>\n");
		sb.append("    <queryId root='2.16.840.1.113883.19.3.2409' extension='1-976-245' displayable='true'/>\n");
		sb.append("    <modifyCode code='CS-CODE'/>\n");
		sb.append("    <responseElementGroupId root='2.16.840.1.113883.19.3.2409' extension='1-976-245' displayable='true'/>\n");
		sb.append("    <responsePriorityCode code='CS-CODE'/>\n");
		sb.append("    <executionAndDeliveryTime value='20020211143035.1600-06'/>\n");
		sb.append("    <statusCode code='CS-CODE'/>\n");
		sb.append("    <parameterList>\n");
		if (pa.getNss() != null && !"".equals(pa.getNss())) {
			sb.append("    <id root='2.16.840.1.113883.19.3.2409' extension='"
					+ pa.getNss() + "' displayable='true'/>\n");
		}
		sb.append("    <dataSource>\n");
		if (pa.getTipoPaciente() != null && !"".equals(pa.getTipoPaciente())) {
			sb.append("    <value root='2.16.840.1.113883.19.3.2409' extension='"
					+ pa.getTipoPaciente() + "' displayable='true'/>\n");
		}
		sb.append("    <semanticsText>The string.</semanticsText>\n");
		sb.append("    </dataSource>\n");
		sb.append("    <patientIdentifier>\n");
		if (pa.getIdee() != null && !"".equals(pa.getIdee())) {
			sb.append("    <id root='2.16.840.1.113883.19.3.2409' extension='"
					+ pa.getIdee() + "' displayable='true'/>\n");
		}
		if (pa.getAgregadoMedico() != null
				&& !"".equals(pa.getAgregadoMedico())) {
			sb.append("    <value root='2.16.840.1.113883.19.3.2409' extension='"
					+ pa.getAgregadoMedico() + "' displayable='true'/>\n");
		}
		sb.append("    <semanticsText>The string.</semanticsText>\n");
		sb.append("    </patientIdentifier>\n");
		sb.append("    </parameterList>\n");
		sb.append("    </QueryByParameter>\n");
		sb.append("    </Body>\n");
		sb.append("  </GovTalkMessage>\n");
		sb.append("</consultarPAIMP>\n");
		return sb.toString();
	}
}
